package framework.classification.entities.lattice.erca;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;

import com.googlecode.erca.Attribute;
import com.googlecode.erca.Entity;
import com.googlecode.erca.ValuedAttribute;
import com.googlecode.erca.clf.Concept;
import com.sun.org.apache.bcel.internal.generic.GETSTATIC;

import framework.classification.entities.ClAbstractEntity;
import framework.classification.entities.ClInterfaceProvided;
import framework.classification.entities.ClInterfaceRequired;
import framework.entity.ACLComponent;
import framework.entity.ACLInterface;

public class LatticeComponentErca extends LatticeAbstractErca {

	public void calculateReduced(ClAbstractEntity table) {

		conceptToExtends = new HashMap<String, ArrayList<String>>();
		realOperations = new HashMap<String, String>();
		abstractOperations = new HashMap<String, String>();

		String name = lattice.getName();
		for (int i = 0; i < lattice.getConcepts().size(); i++) {
			Concept concept = lattice.getConcepts().get(i);
			concept.setName("C"
					+ concept.getName().substring(
							concept.getName().indexOf("_") + 1));
			caculateOperationConcept(concept,table);
		}

	}

	public void caculateOperationConcept(Concept concept,
			ClAbstractEntity table) {

		//soit le concept à un extent, dans ce cas il represente une interface deja definis
		if (!concept.getSimplifiedExtent().isEmpty()){
			for (Entity ent : concept.getSimplifiedExtent()){

				ACLComponent aclcompo = new ACLComponent(ent.getName());
				ArrayList<ACLInterface> interspro = table.getAbstractClassfication().getStructure().getComponentsProvided().get(ent.getName());
				ArrayList<ACLInterface> intersreq = table.getAbstractClassfication().getStructure().getComponentsRequired().get(ent.getName());
				for (ACLInterface aclinter : interspro){
					aclcompo.addInterfacePro(aclinter);
				}
				for (ACLInterface aclinter : intersreq){
					aclcompo.addInterfaceReq(aclinter);

				}	
				
				if (realOperations.containsKey(aclcompo.toString())){
				
					//System.out.println(aclcompo.getName()+" "+concept.getName());
					
					
				}
			
				realOperations.put(aclcompo.toString(),concept.getName());
				
				
				if (!conceptToExtends.containsKey(concept.getName()))
					conceptToExtends.put(concept.getName(),new ArrayList<String>());
				if (!conceptToExtends.get(concept.getName()).contains(aclcompo.toString()))
					conceptToExtends.get(concept.getName()).add(aclcompo.toString());

				if (lattice.getTop() == concept) superEntity = aclcompo.toString();

				//affichage à enlever
				//				System.out.println(aclcompo.getName());
				//				for (ACLInterface interreq : aclcompo.getInterfacesReq()){
				//					System.out.println("\t"+interreq.getName());
				//				}
				//				System.out.println("------------------------------------------");
				//				for (ACLInterface interpro : aclcompo.getInterfacesPro()){
				//					System.out.println("\t"+interpro.getName());
				//				}
				//				System.out.println();
			}

		}
		//soit les extents simplifies sont vide, dans ce cas on reconstruit le composant abstraite
		//à partir des concepts parents;
		else{

			//nouveau composant
			ACLComponent aclcompo = new ACLComponent(table.getName()+concept.getName());
			//liste d'interface à ne  pas inclure 
			ArrayList<String> nointers = new ArrayList<String>();


			//pour tous les concpets parents
			for (Concept parentConcept : concept.getAllParents()){


				//on parcours tous les attributs simplifiés
				for (Attribute att : parentConcept.getSimplifiedIntent()){

					String typeatt = att.getDescription().substring(0,att.getDescription().indexOf("="));
					String nameatt = att.getDescription().substring(att.getDescription().indexOf("=")+1);

					//si l'attribut est de type requis
					if (typeatt.equals("Req")){



						// si l'attribut est de type not, on l'inserer dans la liste puis on enlevera toutes les interfaces
						//de ce type dans le composant final

						if (nameatt.charAt(0) == '!') nointers.add(table.getAbstractClassfication().getInterfacesRequired().get(nameatt.substring(1)).getLattice().getMaxSuperEntity());
						else{
							//on recupere la definition de l'interface et sa classification
							ACLInterface aclinterAtt = table.getAbstractClassfication().getInterfacesNames().get(nameatt);
							ClInterfaceRequired clinter = table.getAbstractClassfication().getInterfacesRequired().get(nameatt);


							Boolean add = true;
							ArrayList<ACLInterface> remove = new ArrayList<ACLInterface>();

							//on chack la nouvelle interface avec celle deja presente dans le composant
							for (ACLInterface aclinterComp : aclcompo.getInterfacesReq()){

								//si une interface deja presente dans le composant est  parent de la nouvelle interface attribut
								// on echange les deux interfaces
								if (clinter.getLattice().isParent(aclinterComp.toString(),aclinterAtt.toString()))
									remove.add(aclinterComp);
								//si la nouvelle interface est parent d'une des interface deja presente dans le composant
								//on ne l'ajoute pas
								else if (clinter.getLattice().isParent(aclinterAtt.toString(),aclinterComp.toString()))
									add = false;

								//dans le dernier cas add =true donc on ajoute l'interface aux composant

							}
							if (add){
								if (!remove.isEmpty()){

									for (ACLInterface aclinter : remove){

										aclcompo.getInterfacesReq().remove(aclinter);
									}
								}
								aclcompo.getInterfacesReq().add(aclinterAtt);
							}

						}

					}
					//si l'attribut est de type fournis
					else{

						//on recupere la definition de l'interface et sa classification
						ACLInterface aclinterAtt = table.getAbstractClassfication().getInterfacesNames().get(nameatt);
						ClInterfaceProvided clinter = table.getAbstractClassfication().getInterfacesProvided().get(nameatt);

						Boolean add = true;
						ArrayList<ACLInterface> remove = new ArrayList<ACLInterface>();

						//on chack la nouvelle interface avec celle deja presente dans le composant
						for (ACLInterface aclinterComp : aclcompo.getInterfacesPro()){

							//si une interface deja presente dans le composant est  parent de la nouvelle interface attribut
							// on echange les deux interfaces
							if (clinter.getLattice().isParent(aclinterComp.toString(),aclinterAtt.toString()))
								remove.add(aclinterComp);
							//si la nouvelle interface est parent d'une des interface deja presente dans le composant
							//on ne l'ajoute pas
							else if (clinter.getLattice().isParent(aclinterAtt.toString(),aclinterComp.toString()))
								add = false;

							//dans le dernier cas add =true donc on ajoute l'interface aux composant

						}
						if (add){
							if (!remove.isEmpty()){

								for (ACLInterface aclinter : remove){

									aclcompo.getInterfacesPro().remove(aclinter);
								}
							}
							aclcompo.getInterfacesPro().add(aclinterAtt);
						}
					}

				}

			}

			for (int i=0;i<nointers.size();i++){

				for (int j=0;j<aclcompo.getInterfacesReq().size();j++){


					ClInterfaceRequired clinter = table.getAbstractClassfication().getInterfacesRequired().get(aclcompo.getInterfacesReq().get(j).getName());
					if (clinter.getLattice().getMaxSuperEntity().equals(nointers.get(i)))
						aclcompo.getInterfacesReq().remove(j);

				}

			}
			abstractOperations.put(aclcompo.toString(),concept.getName());
		
			if (!conceptToExtends.containsKey(concept.getName()))
				conceptToExtends.put(concept.getName(),new ArrayList<String>());
			if (!conceptToExtends.get(concept.getName()).contains(aclcompo.toString()))
				conceptToExtends.get(concept.getName()).add(aclcompo.toString());

			if (lattice.getTop() == concept) superEntity = aclcompo.toString();


			//affichage à enlever
			//			System.out.println(aclcompo.getName());
			//			for (ACLInterface interreq : aclcompo.getInterfacesReq()){
			//				System.out.println("\t"+interreq.getName());
			//			}
			//			System.out.println("------------------------------------------");
			//			for (ACLInterface interpro : aclcompo.getInterfacesPro()){
			//				System.out.println("\t"+interpro.getName());
			//			}
			//			System.out.println(nointers);
			//			System.out.println("===================================================");
		}



	}

}


